//package org.artifact.core.plugin.csv;
//
//import cn.hutool.core.io.FileUtil;
//import cn.hutool.core.io.watch.WatchMonitor;
//import cn.hutool.core.io.watch.Watcher;
//import cn.hutool.core.text.csv.CsvData;
//import cn.hutool.core.text.csv.CsvReadConfig;
//import cn.hutool.core.text.csv.CsvReader;
//import cn.hutool.core.util.ClassUtil;
//import cn.hutool.core.util.ReflectUtil;
//import cn.hutool.core.util.StrUtil;
//import cn.hutool.crypto.SecureUtil;
//import cn.hutool.http.HttpUtil;
//import cn.hutool.log.Log;
//import cn.hutool.log.LogFactory;
//import cn.hutool.setting.Setting;
//import net.sf.cglib.proxy.Enhancer;
//import net.sf.cglib.proxy.MethodInterceptor;
//import net.sf.cglib.proxy.MethodProxy;
//import org.artifact.core.db.BaseCsv;
//import org.artifact.core.lang.AbstractPlugin;
//import org.yaml.snakeyaml.Yaml;
//
//import java.io.File;
//import java.io.FileFilter;
//import java.io.FileInputStream;
//import java.io.FileNotFoundException;
//import java.lang.reflect.Method;
//import java.nio.charset.Charset;
//import java.nio.file.Path;
//import java.nio.file.WatchEvent;
//import java.util.HashMap;
//import java.util.LinkedHashMap;
//import java.util.List;
//import java.util.Map;
//
//public class CsvPlugin<E> extends AbstractPlugin {
//
//	static final Log log = LogFactory.get(CsvPlugin.class);
//
//	static final int CSV_HEAD_ROW_COUNT = 4;
//
//	/** 下载路径 */
//	private String downloadUrl;
//	/** 校验文件名 */
//	private String verifyFileName;
//	/** CSV文件夹 */
//	private String csvFolderPath;
//	/** 提供器的包 */
//	private String providerPackage;
//	/** 监控 */
//	private boolean monitor;
//
//	private WatchMonitor watchMonitor;
//
//	private CsvReader reader;
//
//	private CsvHelper helper;
//
//
//	public CsvPlugin() {
//		super();
//	}
//
//
//	public CsvPlugin(String downloadUrl, String verifyFileName, String csvFolderPath,String providerPackage, boolean monitor,E extendProxy) {
//		super();
//		this.downloadUrl = downloadUrl;
//		this.verifyFileName = verifyFileName;
//		this.csvFolderPath = csvFolderPath;
//		this.providerPackage = providerPackage;
//		this.monitor = monitor;
//		CsvReadConfig config = new CsvReadConfig();
//    	config.setFieldSeparator(';');
//    	this.reader = new CsvReader(config);
//    	this.helper = new CsvHelper(extendProxy);
//	}
//
//
//	public CsvHelper getHelper() {
//		return helper;
//	}
//
//
//
//
//	@Override
//	public boolean start() {
//
//		try {
//			// 1.下载
//			if (StrUtil.isNotBlank(downloadUrl)) {
//				download();
//			}
//
//
//	    	// 2.加载
//			List<File> files =FileUtil.loopFiles(csvFolderPath, new FileFilter() {
//				@Override
//				public boolean accept(File pathname) {
//					return StrUtil.endWith(pathname.getName(), ".csv") || StrUtil.endWith(pathname.getName(), ".yml");
//				}
//			});
//
//			for (File file : files) {
//				if (StrUtil.endWith(file.getName(), ".csv")) {
//					paddingTable(file);
//				}else if (StrUtil.endWith(file.getName(), ".yml")) {
//					paddingGlobal(file);
//				}
//			}
//
//			// 3.监控
//			if (monitor) {
//				monitor();
//			}
//			return true;
//		} catch (Exception e) {
//			log.error(e);
//		}
//		return false;
//	}
//
//	/**
//	 * 填充table
//	 * @param file
//	 */
//	private void paddingTable(File file) {
//		Class<BaseCsv> clazz = getClassByFileName(file.getName());
//		CsvData csvData = reader.read(file);
//		LinkedHashMap<Integer,BaseCsv> csvTable = new LinkedHashMap<>(csvData.getRowCount() - CSV_HEAD_ROW_COUNT);
//		for (int i = CSV_HEAD_ROW_COUNT; i < csvData.getRowCount(); i++) {
//			BaseCsv baseCsv = ReflectUtil.newInstance(clazz,csvData.getRow(i));
//			csvTable.put(baseCsv.getId(),baseCsv);
//		}
//		helper.cacheTable.put(clazz, csvTable);
//	}
//
//	/**
//	 * 填充Global
//	 * @param file
//	 * @throws FileNotFoundException
//	 */
//	private void paddingGlobal(File file) throws FileNotFoundException {
//		Yaml yaml = new Yaml();
//        Map result= (Map) yaml.load(new FileInputStream(file));
//		helper.global.putAll(result);
//	}
//
//
//	/**
//	 * 根据文件名取得结构体名称
//	 * @param fileName
//	 * @return
//	 */
//	private Class<BaseCsv> getClassByFileName(String fileName) {
//		fileName =  StrUtil.removeSuffix(fileName, ".csv");
//		// 2.转驼峰
//		fileName = StrUtil.toCamelCase(fileName);
//		// 3. 首字母大写
//		fileName = StrUtil.upperFirst(fileName);
//
//		Class<BaseCsv> clazz = ClassUtil.loadClass(providerPackage + "." + fileName +"Csv");
//
//		return clazz;
//	}
//
//	/**
//	 * 监控
//	 */
//	private void monitor() {
//		watchMonitor = WatchMonitor.create(csvFolderPath, WatchMonitor.ENTRY_MODIFY);
//
//		watchMonitor.setWatcher(new Watcher(){
//
//    	    @Override
//    	    public void onModify(WatchEvent<?> event, Path currentPath) {
//    	    	String fileName = event.context().toString();
//    	    	Class<BaseCsv> clazz = getClassByFileName(fileName);
//    	    	if (clazz != null) {
//    	    		File file = FileUtil.newFile(csvFolderPath + File.separator + fileName);
//    	    		paddingTable(file);
//				}
//    	    	log.info("修改：{}-> {}", currentPath, fileName);
//    	    }
//
//			@Override
//			public void onCreate(WatchEvent<?> event, Path currentPath) {
//				// TODO Auto-generated method stub
//
//			}
//
//			@Override
//			public void onDelete(WatchEvent<?> event, Path currentPath) {
//				// TODO Auto-generated method stub
//
//			}
//
//			@Override
//			public void onOverflow(WatchEvent<?> event, Path currentPath) {
//				// TODO Auto-generated method stub
//
//			}
//    	});
//
//    	//设置监听目录的最大深入，目录层级大于制定层级的变更将不被监听，默认只监听当前层级目录
//    	watchMonitor.setMaxDepth(3);
//    	//启动监听
//    	watchMonitor.start();
//	}
//
//
//
//	private void download() {
//		// 下载校验文件
//		long contentSize = HttpUtil.downloadFile(downloadUrl + verifyFileName, csvFolderPath);
//		if (contentSize > 0) {
//			Setting setting = new Setting(new File(csvFolderPath + verifyFileName),Charset.forName("UTF-8"),false);
//			setting.forEach((k,v) -> {
//				String fielName = k.toString();
//				if(FileUtil.exist(csvFolderPath + fielName)){
//					String content = FileUtil.readString(csvFolderPath + fielName, "UTF-8");
//					String md5 = SecureUtil.md5(content);
//					// 文件没有变动
//					if (v.equals(md5)) {
//						return;
//					}
//				}
//				HttpUtil.downloadFile(downloadUrl + fielName, csvFolderPath);
//			});
//		}
//	}
//
//	@Override
//	public boolean stop() {
//		if (monitor && watchMonitor!=null) {
//			watchMonitor.stop();
//		}
//		return true;
//	}
//
//
//
//	/**
//	 * 扩展方法拦截器
//	 * @author apple
//	 *
//	 */
//	class ExtendMethodInterceptor implements MethodInterceptor {
//		@Override
//		public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
//			String extendCacheKey = method.getName();
//			for (Object object : args) {
//				extendCacheKey += ("," + object.toString());
//			}
//
//			// 先查找缓存，缓存没有在真实查找
//			Object object = helper.extendCache.computeIfAbsent(extendCacheKey, k -> {
//				try {
//					// 真实查找
//					return proxy.invokeSuper(obj, args);
//				} catch (Throwable e) {
//					e.printStackTrace();
//				}
//				return null;
//			});
//
//			return object;
//		}
//	}
//
//	public class CsvHelper{
//		/**
//		 * 全局配置
//		 */
//		private Map global = new HashMap<>();
//
//		/**
//		 * CSV缓存
//		 */
//		private Map<Class<BaseCsv>, LinkedHashMap<Integer,BaseCsv>> cacheTable = new HashMap<>();
//
//		/**
//		 * 扩展缓存
//		 */
//		private Map<String, Object> extendCache = new HashMap<>();
//		/**
//		 * 代理
//		 */
//		private E proxy;
//
//
//
//		public CsvHelper(E extendProxy) {
//			super();
//			if (extendProxy!=null) {
//				this.proxy = createProxy(extendProxy);
//			}
//		}
//
//
//
//		private E createProxy(E extendProxy) {
//			Enhancer enhancer = new Enhancer();
//	        //设置目标类的字节码文件
//	        enhancer.setSuperclass(extendProxy.getClass());
//	        //设置回调函数
//	        enhancer.setCallback(new ExtendMethodInterceptor());
//	        return (E) enhancer.create();
//		}
//
//
//		@SuppressWarnings({ "unchecked", "unlikely-arg-type" })
//		public <T extends BaseCsv> T getCsv(Class<T> clazz,int id){
//			LinkedHashMap<Integer, BaseCsv> tables = cacheTable.get(clazz);
//			if (tables.containsKey(clazz)) {
//				return null;
//			}
//			return (T) tables.get(id);
//		}
//
//		public Map getGlobal() {
//			return global;
//		}
//
//		public E getProxy() {
//			return proxy;
//		}
//	}
//}
